package com.xuyuan.json.jackson;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.*;
import lombok.Data;
import org.springframework.context.annotation.Configuration;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

@Configuration
public class JacksonTest {
    public static void main(String[] args) throws Exception {
    }


    public static ObjectMapper getObjectMapper() {
        // Spring整合jackson提供了JacksonProperties的配置类
        ObjectMapper mapper = new ObjectMapper();

        // 1、统一配置config
        // mapper.setConfig();
        // 参数为DeserializationConfig或者SerializationConfig,设置 ObjectMapper的所有全局配置
        // DeserializationConfig: 控制反序列化过程中的配置，如如何处理未知属性、类型处理、字段可见性等。
        // SerializationConfig: 控制序列化过程中的配置，如属性的包含策略、日期格式、命名策略等。

        // 2、SerializationConfig和DeserializationConfig的配置
        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); // 设置日期格式
        mapper.setTimeZone(TimeZone.getTimeZone("UTC+8")); // 设置时区。影响日期和时间的格式化和解析。
        mapper.setLocale(Locale.CHINA); // 设置区域设置。影响日期、数字等格式化的本地化设置。
        mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); // 设置JSON和JAVA对象的映射规则

        // mapper.setAccessorNaming(new DefaultAccessorNamingStrategy.Provider()); // 设置属性命名策略。定义如何将 Java 对象的属性名称转换为 JSON 中的字段名称。
        // mapper.setAnnotationIntrospector(); // 设置注解解析器。用于定义如何处理 Jackson 注解，比如 @JsonIgnore 或 @JsonProperty
        // mapper.setBase64Variant(); // 设置 Base64 编码变体。用于指定 JSON 中的 Base64 数据使用的编码方案
        // mapper.setDefaultAttributes(); // 配置默认属性的特性。允许启用或禁用 ObjectMapper 的某些特性（例如是否允许未知属性）
        // mapper.setDefaultTyping(); // 设置默认的类型处理。定义如何处理多态类型（例如使用类型信息进行反序列化）
        // mapper.setHandlerInstantiator(); // 设置处理程序实例化器。用于创建和管理 JSON 处理程序（如序列化器、反序列化器）的实例
        // 设置属性命名策略，与 setAccessorNaming 类似，定义 JSON 字段名称与 Java 属性名称的映射。（LOWER_CASE、LOWER_CAMEL_CASE、KEBAB_CASE）
        // mapper.setMixInResolver(); // 设置 MixIn 解析器。用于配置 MixIn 注解类的解析策略。
        // mapper.setSerializerFactory(); // 设置序列化工厂。用于配置自定义序列化器的创建和管理

        // // 3、DeserializationConfig的配置
        // mapper.setConstructorDetector(); // 设置构造函数检测器。配置如何选择和使用构造函数进行反序列化。
        // mapper.setNodeFactory(); // 设置节点工厂。定义如何创建 JSON 节点（如对象、数组、值等）
        // mapper.setPolymorphicTypeValidator(); // 设置多态类型验证器。用于控制多态类型的验证策略，确保 JSON 数据的类型安全。
        //
        // // 4、SerializationConfig的配置
        // mapper.setDefaultPrettyPrinter(); // 设置默认的漂亮打印器。定义 JSON 序列化时如何美化输出（例如添加缩进）
        // mapper.setFilterProvider();// 设置过滤器提供者。用于动态控制哪些属性在序列化时被包含或排除
        //
        // // 5、ConfigOverrides的配置
        // mapper.setDefaultPropertyInclusion(); // 设置默认属性包含策略。与 setSerializationInclusion 类似，用于设置全局的属性包含策略
        // mapper.setDefaultSetterInfo(); // 设置默认的 setter 方法可见性。控制哪些 setter 方法对 JSON 反序列化可见
        // mapper.setDefaultVisibility(); // 设置默认的可见性。控制 JSON 序列化和反序列化时哪些字段和方法是可见的。
        // mapper.setDefaultLeniency(); // 设置默认宽松性。定义 ObjectMapper 在反序列化时是否宽松对待 JSON 内容（如忽略某些错误）
        // mapper.setDefaultMergeable(); // 设置默认可合并性。用于配置合并 JSON 对象的策略。
        // mapper.setSerializationInclusion(); // 设置序列化包含策略。控制哪些属性在序列化时包含到 JSON 中，例如可以配置仅包含非空属性。
        // mapper.setVisibility(); // 设置属性访问器的可见性。控制特定类型（如字段、方法）的可见性。
        //
        // // 6、InjectableValues的配置
        InjectableValues.Std injectableValues = new InjectableValues.Std();
        injectableValues.addValue("responseTime", new Date());
        mapper.setInjectableValues(injectableValues); // 设置默认的可注入值。允许在反序列化时注入额外的值到Java对象中。
        // // 7、SimpleMixInResolver
        // mapper.setMixIns(); // 设置 MixIn 注解类。允许将自定义注解应用到特定的类上，修改其序列化和反序列化行为。
        // 8、DefaultSerializerProvider的配置
        // mapper.setSerializerProvider(); // 设置序列化提供者。用于提供自定义的序列化策略和上下文。
        // // 9、SubtypeResolver的配置
        // mapper.setSubtypeResolver(); // 设置子类型解析器。用于管理多态类型的子类解析。
        //
        // // 10、开启关闭某个序列化和反序列化的配置
        // mapper.enable();
        // mapper.disable();
        // mapper.configure(); // 配置序列化某一个特定特性与enable和disable方法类似
        // SerializationFeature、DeserializationFeature、JsonParser.Feature、JsonGenerator.Feature

        mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, false);
        mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, false);
        mapper.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, true);
        mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        return mapper;
    }

    public ObjectMapper getObjectMapper1() {
        // TODO 创建定制化配置的ObjectMapper - 1
        // （1） 创建ObjectMapper
        ObjectMapper mapper = new ObjectMapper();
        // （2） 添加配置
        // SerializationFeature、DeserializationFeature、JsonParser.Feature、JsonGenerator.Feature

        // TODO 创建定制化配置的ObjectMapper - 2
        // （1）创建JsonFactory
        // JsonFactory jsonFactory = JsonFactory.builder().configure().build();
        // （2）添加jsonFactory定制配置
        // （3）创建对应的objectMapper
        // ObjectMapper objectMapper = new ObjectMapper(jsonFactory);

        // TODO 创建定制化配置的ObjectMapper - 3
        // （1）创建JsonFactory
        // （2）创建DefaultSerializerProvider

        // （3）创建DefaultDeserializationContext
        return mapper;
    }

    // 原始类
    @Data
    public static class Person1 {
        public String name;
        public int age;
        public String email;
    }

    // 混合类，用于向Person类添加或覆盖注解
    abstract class PersonMixIn {
        @JsonIgnore
        public abstract String getEmail();
    }
}
